import { _decorator, Component, instantiate, Node, Prefab, SpriteFrame } from 'cc';
import DataManager from '../Global/DataManager';
import { JoyStickmanager } from '../UI/JoyStickmanager';
import { ResourceManager } from '../Global/ResourceManager';
import { ActorManager } from '../Entity/Actor/ActorManager';
import { EventEnum, PrefabPathEnum, TexturePathEnum } from '../Enum';
import { ApiMsgEnum, EntityTypeEnum, IClientInput, IMsgClientSync, IMsgServerSync, InputTypeEnum } from '../Common';
import { BulletManager } from '../Entity/Bullet/BulletManager';
import { ObjectPoolManager } from '../Global/ObjectPoolManager';
import { NetworkManager } from '../Global/NetworkManager';
import EventManager from '../Global/EventManager';
import { deepClone } from '../Utils';
const { ccclass, property } = _decorator;

@ccclass('BattleManager')
export class BattleManager extends Component {
    private stage:Node;
    private UI:Node;
    private shouldUpdate:boolean=false;// 是否更新

    private pendingMsg:IMsgClientSync[]=[];//记录预测的

    protected onLoad(): void {

    }
    protected async start(): Promise<void> {
        this.clearGame();
        await Promise.all([
            this.connectServer(),
             this.loadRes()
        ]);
        // const {success,error,res}=await NetworkManager.Instance.callApi(ApiMsgEnum.ApiPlayerJoin,"我是coocs")
        // if(!success){
        //     console.error("连接失败"+error);
        //     return;
        // }
        // console.log("连接成功 res"+res);
        this.initGame();

    }

    initGame(){
    
        DataManager.Instance.jm = this.UI.getChildByName("JoyStick").getComponent(JoyStickmanager);
        DataManager.Instance.stage=this.stage;
        if(!DataManager.Instance.jm){
            console.error("没找到 JoyStickmanager");
        }
      this.initMap();
       this.shouldUpdate=true;
       console.log("资源加载完成");


        EventManager.Instance.on(EventEnum.ClientSyn,this.handleClientSync,this)
        NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync,this.handleServerSync,this);
    }
    clearGame(){
        EventManager.Instance.off(EventEnum.ClientSyn,this.handleClientSync,this);
        NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgServerSync,this.handleServerSync,this);

        this.stage = this.node.getChildByName("Stage");
        this.UI = this.node.getChildByName("UI");
        if(!this.stage||!this.UI){
            console.error("没找到 Stage 或UI");
        }
        this.stage.destroyAllChildren();// 清空测试用的子节点
    }
    async connectServer(){
       if(!await NetworkManager.Instance.connect().catch(()=>false)){
        console.error("连接失败");
        console.log("正在重试");
        await new Promise((rs)=>setTimeout(rs,1000));
          await this.connectServer();
        }
    }
    protected update(dt: number): void {
        if(!this.shouldUpdate){
            return
        }  
        this.render();
        this.tick(dt);
    }
    tick(dt){
        this.tickActor(dt);

        // DataManager.Instance.applyInput({
        //     type:InputTypeEnum.TimePast,
        //     dt,
        // })
    }
    // 更新角色
    tickActor(dt: number) {
        for(const data of DataManager.Instance.state.actor){
            const{id}=data;
            let am=DataManager.Instance.actorMap.get(id);
            am.tick(dt);
        }
    }
    initMap(){
        // 创建地图
        const map=instantiate(DataManager.Instance.prefabMap.get(EntityTypeEnum.Map));
        this.stage.addChild(map);
    }

    // 加载资源 把预制体加载好
    async loadRes(){
        const list=[];
        for(const type in PrefabPathEnum){
            const p= ResourceManager.Instance.loadRes(PrefabPathEnum[type],Prefab).then((prefab)=>{
                DataManager.Instance.prefabMap.set(type,prefab);
            })
            list.push(p);
        }
        for(const type in TexturePathEnum){
            const p= ResourceManager.Instance.loadDir(TexturePathEnum[type],SpriteFrame).then((spriteFrames)=>{
                DataManager.Instance.textureMap.set(type,spriteFrames);
                console.log(`${type} 加载完成`);
                console.log(spriteFrames.find);
            })
            list.push(p);
        }

        await Promise.all(list);// 等待所有资源加载完成
    }

    render(){
        this.renderActor();
        this.renderBullet();
    }
    renderBullet(){
        for(const data of DataManager.Instance.state.bullet){
            const {id ,type}=data
            let bm=DataManager.Instance.bulletMap.get(id);
            if(!bm){
                // 如果没有 创建并初始化角色
                // const prefab=DataManager.Instance.prefabMap.get(EntityTypeEnum[type]);
                let bullet=ObjectPoolManager.Instance.get(type);
                // this.stage.addChild(bullet);
                bm=bullet.getComponent(BulletManager)||bullet.addComponent(BulletManager);
                DataManager.Instance.bulletMap.set(data.id,bm);
                bm.init(data);//  初始化角色
            }
            else{
                bm.render(data);//  更新角色
            }
        }
    }
     renderActor(){
        for(const data of DataManager.Instance.state.actor){
            const {id ,type}=data
            let am=DataManager.Instance.actorMap.get(id);
            if(!am){
                // 如果没有 创建并初始化角色
                const prefab=DataManager.Instance.prefabMap.get(EntityTypeEnum[type]);
                let actor=instantiate(prefab);
                this.stage.addChild(actor);
                am=actor.addComponent(ActorManager);
                DataManager.Instance.actorMap.set(data.id,am);
                am.init(data);//  初始化角色
            }
            else{
                am.render(data);//  更新角色
            }
        }
    }
    handleClientSync(input:IClientInput){
        const msg:IMsgClientSync={
            input,
            frameId:DataManager.Instance.frameId++,
        }
        NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync,msg);
        if(input.type===InputTypeEnum.ActorMove){
            DataManager.Instance.applyInput(input);//预测
            this.pendingMsg.push(msg);
        }
   
    }

    handleServerSync({inputs,lastFrameId}:IMsgServerSync){
        DataManager.Instance.state=DataManager.Instance.lastState;
        for(const input of inputs){
            DataManager.Instance.applyInput(input);
            // console.log("收到数据了");
        }

        DataManager.Instance.lastState=deepClone(DataManager.Instance.state);

        this.pendingMsg=this.pendingMsg.filter((msg)=>msg.frameId>lastFrameId);

        for(const msg of this.pendingMsg){
            DataManager.Instance.applyInput(msg.input);
            // console.log("收到数据了");
        }

    }
}

